# Copyright (c) Injasuti Consulting Limited. All rights reserved.
# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
# Description: This script enumerates the SharePoint farm and writes the output to an Xml file.
# Platform   : Tested on the following platforms - Windows Server 2008, Windows Server 2008 R2, SharePoint Server 2010
# ========================================

# PARAMETERS
# ========================================
param([string] $outputFileName, [switch] $exportSolutions, [switch] $nocls)

# GLOBAL VARIABLES
# ========================================
#$ErrorActionPreference = "Stop"

$xml = New-Object xml

# LOAD ASSEMBLIES
# ========================================

# EXTERNAL FUNCTIONS
# ========================================

# FUNCTIONS
# ========================================

function Add-Attribute([object] $xmlNode, [string] $attributeName, [string] $attributeValue)
{
    $attribute = $xml.CreateAttribute($attributeName)
    $attribute.Value = $attributeValue
    [void]$xmlNode.Attributes.Append($attribute)
}

# MAIN
# ========================================

if ($nocls -eq $false) { CLS }

# ========================================

$root = $xml.CreateElement("Farm")
[void]$xml.AppendChild($root)

# Farm
$spFarm = Get-SPFarm
Add-Attribute $root "Name" $spFarm.Name
Add-Attribute $root "DisplayName" $spFarm.DisplayName

# TODO: Farm Features
# http://geekswithblogs.net/bjackett/archive/2009/10/08/powershell-script-find-all-sharepoint-features-installed-on-farm.aspx

# Farm Servers
$xmlServers = $xml.CreateElement("Servers")
[void]$root.AppendChild($xmlServers)
foreach ($spServer in $spFarm.Servers)
{
    $xmlServer = $xml.CreateElement("Server")
    [void]$xmlServers.AppendChild($xmlServer)
    Add-Attribute $xmlServer "Name" $spServer.Name
}

# Farm Solutions
$xmlSolutions = $xml.CreateElement("Solutions")
[void]$root.AppendChild($xmlSolutions)
foreach ($spSolution in $spFarm.Solutions)
{
    $xmlSolution = $xml.CreateElement("Solution")
    [void]$xmlSolutions.AppendChild($xmlSolution)
    Add-Attribute $xmlSolution "Name" $spSolution.Name
    Add-Attribute $xmlSolution "DeploymentState" $spSolution.DeploymentState
    Add-Attribute $xmlSolution "ContainsGlobalAssembly" $spSolution.ContainsGlobalAssembly
}

# Farm Services
$xmlServices = $xml.CreateElement("Services")
[void]$root.AppendChild($xmlServices)
foreach ($spService in $spFarm.Services)
{
    $xmlService = $xml.CreateElement("Service")
    [void]$xmlServices.AppendChild($xmlService)
    Add-Attribute $xmlService "TypeName" $spService.TypeName
    Add-Attribute $xmlService "Type" $spService.GetType().Name
    Add-Attribute $xmlService "DisplayName" $spService.DisplayName
    Add-Attribute $xmlService "Name" $spService.Name
    
    # Web Applications
    if ($spService.GetType().Name -eq "SPWebService")
    {
        $xmlWebApplications = $xml.CreateElement("WebApplications")
        [void]$xmlService.AppendChild($xmlWebApplications)
        foreach ($spWebApp in $spService.WebApplications)
        {
            $xmlWebApp = $xml.CreateElement("WebApplication")
            [void]$xmlWebApplications.AppendChild($xmlWebApp)
            Add-Attribute $xmlWebApp "Type" $spWebApp.GetType().Name
            Add-Attribute $xmlWebApp "TypeName" $spWebApp.TypeName
            Add-Attribute $xmlWebApp "Name" $spWebApp.Name
            Add-Attribute $xmlWebApp "DisplayName" $spWebApp.DisplayName
            Add-Attribute $xmlWebApp "Url" $spWebApp.Url
            # TODO: Add-Attribute $xmlWebApp "Port" $spWebApp.???

            # TODO: Databases

            # TODO: Zones

            # TODO: Alternate Access Mappings

            # Managed Paths
            $xmlManagedPaths = $xml.CreateElement("ManagedPaths")
            [void]$xmlWebApp.AppendChild($xmlManagedPaths)
            $spManagedPaths = Get-SPManagedPath -WebApplication $spWebApp.url
            foreach ($spManagedPath in $spManagedPaths)
            {
                # Managed Path
                $xmlManagedPath = $xml.CreateElement("ManagedPath")
                [void]$xmlManagedPaths.AppendChild($xmlManagedPath)
                Add-Attribute $xmlManagedPath "Name" $spManagedPath.Name
                Add-Attribute $xmlManagedPath "Type" $spManagedPath.Type
            }
            
            # Site Collections
            $xmlSiteCollections = $xml.CreateElement("SiteCollections")
            [void]$xmlWebApp.AppendChild($xmlSiteCollections)
            $spSiteCollections = Get-SPSite -WebApplication $spWebApp.url -Limit ALL
            foreach ($spSiteCollection in $spSiteCollections)
            {
                # Site Collection
                $xmlSiteCollection = $xml.CreateElement("SiteCollection")
                [void]$xmlSiteCollections.AppendChild($xmlSiteCollection)
                Add-Attribute $xmlSiteCollection "Url" $spSiteCollection.Url
                Add-Attribute $xmlSiteCollection "ID" $spSiteCollection.ID
                Add-Attribute $xmlSiteCollection "Port" $spSiteCollection.Port
                Add-Attribute $xmlSiteCollection "ServerRelativeUrl" $spSiteCollection.ServerRelativeUrl

                # TODO: Databases
                # TODO: Site Collection Administrators
                # TODO: Features
                # TODO: Site Collection Groups
                # TODO: Webs
                # TODO: Web
                # TODO: Features
                # TODO: Groups
                # TODO: Lists
            }
        }
    }
}

# ========================================

# Save output
$xml.Save("c:\temp\Farm.xml")
Get-Content c:\temp\Farm.xml

# END
# ========================================
